import java.util.Arrays;
import java.util.Random;

public class BubbleSort {

    public static void main(String[] args) {
        int[] arr = new int[100];
        for (int i =0;i<100;i++){
            arr[i] = new Random().nextInt(100000);
        }
//        System.out.println("排序前" + Arrays.toString(arr));
//        bubbleSort(arr);
//        System.out.println("排序后" + Arrays.toString(arr));
        long start = System.currentTimeMillis();
        bubbleSortF(arr,arr.length-1);
        long end = System.currentTimeMillis();
        System.out.println("耗时"+ ((end - start)));
        System.out.println(Arrays.toString(arr));
        System.out.println("------------------------------");

//        System.out.println("排序前" + Arrays.toString(arr));
//        bubbleSort2(arr);
//        System.out.println("排序后" + Arrays.toString(arr));
    }


    /**
     * 普通的冒泡排序
     * @param arr
     */
    public static void bubbleSort(int[] arr) {
        //外层确定边界
        for (int i = arr.length -1 ;i >= 0;i--){
            //内层遍历交换，
            for (int j=0;j<i;j++){
                if (arr[j] > arr[j+1]){
                    int t = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = t;
                }
            }
        }
    }

    /**
     * 优化后的冒泡排序，解决如果已经排序完成，但仍然继续缩小边界的问题
     * @param arr
     */
    public static void bubbleSort2(int[] arr) {
        //外层确定边界

        for (int i = arr.length -1;i >= 0;i--){
            //设置一个记录交换点的变量
            int x = 0;
            //内层遍历交换，
            for (int j=0;j<i;j++){
                if (arr[j] > arr[j+1]){
                    int t = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = t;

                    //发生交换后则把j赋值给x，这样就能确保如果后面一段是连续的则不用重复遍历
                    x = j;
                }
            }
            //赋值缩小边界
            i =x;
        }
    }


    /**
     * 优化后的冒泡排序，解决如果已经排序完成，但仍然继续缩小边界的问题.
     * 递归版本
     * @param arr
     */
    public static void bubbleSortF(int[] arr,int x) {
        if (x == 0){
            return;
        }
        //记录是否发生交换的索引
        int index = 0;
            //内层遍历交换，
            for (int j=0;j<x;j++){
                if (arr[j] > arr[j+1]){
                    int t = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = t;

                    //发生交换后则把j赋值给x，这样就能确保如果后面一段是连续的则不用重复遍历
                    index = j;
                }
            }
            x = index;
            bubbleSortF(arr,x);
        }
    }





